#include <stdlib.h>
#ifdef __linux__
#include <sys/time.h>
#endif
#include <string>
#include <iostream>
#include <memory>
#include <rise/common/exmacros.h>
#include <rise/common/Log.h>
#include <rise/common/Exception.h>
#include <rise/common/DataEncoder.h>
#include <rise/common/StreamBuffer.h>
#include <rise/common/PerformanceCounter.h>
#include <staff/common/Value.h>
#include <staff/common/QName.h>
#include <staff/common/Attribute.h>
#include <staff/common/DataObject.h>
#include <staff-mq/client/Message.h>
#include <staff-mq/client/Subscriber.h>

#ifdef WIN32
  LARGE_INTEGER g_llFrequency = {0};
  BOOL g_bQueryResult = QueryPerformanceFrequency(&g_llFrequency);
#endif

long long GetCurrentTime()
{
#ifdef WIN32
  LARGE_INTEGER llPerf = {0};
  QueryPerformanceCounter(&llPerf);
  return llPerf.QuadPart * 1000ll / ( g_llFrequency.QuadPart / 1000ll);
#else
  struct timeval stTimeVal;
  gettimeofday(&stTimeVal, NULL);
  return stTimeVal.tv_sec * 1000000ll + stTimeVal.tv_usec;
#endif
}

class MyMessageHandler: public smq::MessageHandler
{
public:
  virtual void operator()(smq::Subscriber& rSubscriber, const smq::Message& rMsg)
  {
    long long llReceiveTime = GetCurrentTime();
    const staff::CDataObject& rdoMsg = rMsg.tdoMessage;
    long long llSendTime = rdoMsg.GetChildByLocalName("Time").GetValue();

    int nMsgSize = rdoMsg.GetChildByLocalName("Size").GetValue();

    std::cout << "Message id: " << rMsg.sId << " size: " << nMsgSize << " delivered in: " << (llReceiveTime - llSendTime) << " microsecond " << std::endl;
  }
};


int main(int nArgs, char* szArgs[])
{
  std::string sServerHost = "127.0.0.1";
  unsigned short ushServerPort = 8768;

  for (int nArg = 1; nArg < nArgs; ++nArg)
  {
    if(szArgs[nArg])
    {
      const std::string& sArg = std::string(szArgs[nArg]);
      if (sArg.substr(0, 2) == "-s")
      {
        sServerHost = sArg.substr(2);
      }
      else
      if (sArg.substr(0, 2) == "-p")
      {
        ushServerPort = static_cast<unsigned short>(atoi(sArg.substr(2).c_str()));
      }
      else
      if (sArg.substr(0, 2) == "-h")
      {
        std::cerr << "Subscriber sample.\n\n"
            << szArgs[0] << "[ -h][ -s<Server host>][ -p<port>]\n\n";
        return 0;
      }
      else
      {
        std::cerr << "unknown arg: " << sArg << "\n";
        return 1;
      }
    }
  }

  try
  {
    MyMessageHandler tMessageHandler;

    smq::Subscriber tSubscriber;
    tSubscriber.Init("subscriber-bin-bench", sServerHost, ushServerPort);
    tSubscriber.SetHandler(&tMessageHandler);

    std::cout << "subscribing to \"queue-bin-bench\"" << std::endl;
    tSubscriber.Subscribe("queue-bin-bench");

    tSubscriber.Start();
  }
  RISE_CATCH_ALL

  return 0;
}
